package server;

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;

/**
 * @file Server.java
 *
 * @version 0.5
 * @author James Dibble 10009689
 * 
 * Requires Java 7.  Uses java.Files.readAllBytes()
 * 
 * Latest Source:
 * http://code.google.com/p/csp-server/source/browse/
 *                                           trunk/Server/src/server/Server.java
 * Issues:
 * 1. When a client disconnects an object still exists in the clients array.
 * Link: http://code.google.com/p/csp-server/issues/detail?id=3&can=1
 */
public class Server extends Thread {
    // <editor-fold defaultstate="collapsed" desc="Attributes">
    private ServerSocket ssMySocket;
    public static ArrayList<Client_Handler> clients;
    public static boolean bolServerAlive, bolServerDebug;
    private Server_Type serverType;
    private Resources resources;
    // </editor-fold>

    // <editor-fold defaultstate="collapsed" desc="Constructors">
    /**
     * Create a new file server.
     *
     * @param intPort
     * @param serverType 
     * @throws IOException  
     */
    public Server(int intPort, Server_Type serverType) throws IOException {
        this.ssMySocket = new ServerSocket(intPort);
        Server.clients = new ArrayList<>();
        Server.bolServerAlive = true;
        this.serverType = serverType;
        resources = new Resources();
        bolServerDebug = false;
        
        //ADD RESOURCES
        resources.AddResource(new Resource(1, 
                                           "myProgram.jar", 
                                           "A computer program", 
                                           "The program displays a message", 
                                           "newProgram.jar")
                              );
        resources.AddResource(new Resource(2, 
                                           "computer-recovery.jpg", 
                                           "A Jpeg picture", 
                                           "This picture shows …", 
                                           "newPicture.jpg")
                              );
        resources.AddResource(new Resource(3, 
                                           "myBook.txt", 
                                           "An e-book", 
                                           "The book is about …", 
                                           "newBook.txt")
                              );
    }
    // </editor-fold>

    // <editor-fold defaultstate="collapsed" desc="Methods">
    @Override
    public void run() {
        //Loop until user kills the server or Server Socket is closed abnormally
        while (bolServerAlive && !ssMySocket.isClosed()) {
            try {
                Socket newClientSocket = ssMySocket.accept();
                System.out.println(
                        String.format("Connection recieved from (%s).",
                        newClientSocket.getInetAddress().toString())
                );
                Client_Handler newClient = new Client_Handler(newClientSocket, 
                                                              this
                                                              );
                new Thread(newClient).start();
                clients.add(newClient);
            } catch (IOException ex) {
                if (ex.getCause() != null) {
                    if(bolServerDebug)ex.printStackTrace(System.out);
                    System.out.println("Could not accept new Client.");
                }
            }
        }
    }

    /**
     * Free the port and kill the thread so that no new clients can connect.
     * 
     * @throws IOException 
     */
    public synchronized void KillServer() throws IOException {
        bolServerAlive = false;
        ssMySocket.close();
        for(Client_Handler thisCH: clients){
            thisCH.Disconnect();
        }
        this.interrupt();
        System.out.println("Server Killed.");
    }

    /**
     * Look through the resources on the server for the ID specified.
     * @param ID
     * @return 
     */
    public Resource getResourceByID(int ID) {
        return this.resources.getResourceByID(ID);
    }

    /**
     * Get the style of server that was created.
     * 
     * @return 
     */
    public Server_Type getServerType() {
        return this.serverType;
    }

    /**
     * Get a list of files on the server to send to the client.
     * 
     * @return 
     */
    public String listResources() {
        return resources.listResources();
    }

    /**
     * Turn on verbose output.
     */
    public void toggleDebug() {
        if(bolServerDebug) bolServerDebug = false;
        else bolServerDebug = true;
        System.out.println("Debug mode: " + bolServerDebug);
    }

    /**
     * What type of server has been/is to be created.
     */
    public enum Server_Type {
        /**
         * Server will upload file.
         */
        FILE_SERVER,
        /**
         *  Server will upload description.
         */
        DESCRIPTION_SERVER
    }
    // </editor-fold>
}
